#include "DbTable.h"

DbTable::DbTable(char* dbPath, string tableName, int id)
	:mId(id)
	,mDb(new Database(dbPath))
	,mTableName(tableName)
{
	mData = Load();
	mNewData = mData;
}
DbTable::~DbTable()
{
	delete mDb;
	mDb = 0;
}

bool DbTable::Delete()
{
	if(mId > 0)
	{
		stringstream ss;
		ss << "DELETE FROM " << mTableName << " WHERE id = '" << mId << "';";

		if(mDb->Execute(ss.str()))
		{
			mId = 0;
			mData = Load();
			mNewData = mData;
			return true;
		}
		else return false;
	}
	else
	{
		cout << "No data loaded for this object" << endl;
		return false;
	}
}

string DbTable::Get(string fieldName)
{
	return mData[fieldName];
}

bool DbTable::IdExists(int id)
{
	stringstream ss;
	ss << "SELECT 1 FROM " << mTableName << " WHERE id = '" << id << "';";

	vector<string> vLine = mDb->GetLine(ss.str());
		
	bool exists = false;
	if(vLine.size() > 0)
	{
		string ans = vLine.at(0);
		if(ans == "1")
			exists = true;
	}
	return exists;
}

map<string, string> DbTable::Load()
{
	map<string, string> vReturn;
	vector<string> colsName = mDb->GetColumnsName(mTableName);
		
	if(mId > 0)
	{
		stringstream ss;
		ss << "SELECT * FROM " << mTableName << " WHERE id = '" << mId << "';";
		vector<string> vRecived = mDb->GetLine(ss.str());

		int i = 0;
		for(vector<string>::iterator it = vRecived.begin(); it < vRecived.end(); ++it)
		{
			string data = *it;
			vReturn[colsName.at(i++)] = data;
		}
	}
	else
	{
		for(vector<string>::iterator it = colsName.begin(); it < colsName.end(); ++it)
		{
			string data = *it;
			vReturn[data] = "";
		}
	}
	return vReturn;
}

int DbTable::Save()
{
	//Returns INT which is the ID of the saved data line $db = CDB::getDb();
	int dataId = 0;
		
	if(IdExists(mId))
	{
		//If the ID already exists, Update the existing data
		stringstream SQL;
		SQL << "UPDATE " << mTableName << " SET ";

		int i = 0;
		for(map<string, string>::iterator it = mNewData.begin(); it != mNewData.end(); ++it)
		{
			if(i == 0)
				SQL << it->first << " = '" << it->second << "'";
			else
				SQL << ", " << it->first << " = '" << it->second << "'";
			i++;
		}
		SQL << " WHERE id = '" << mId << "';";
			
		if(!mDb->Execute(SQL.str()))
		{
			cout << "Unable to complete the execution of the SQL Request" << endl;
			cout << "Query: " << SQL.str() << endl;
		}
		else
			dataId = mId;
	}
	else
	{			
		//If the ID don't exists, Insert a new row
		stringstream SQL;
		SQL << "INSERT INTO " << mTableName << " VALUES (";
		int i = 0;
		
		vector<string> colsName = mDb->GetColumnsName(mTableName);
		for(vector<string>::iterator it = colsName.begin(); it < colsName.end(); ++it)
		{
			if(i == 0)
				SQL << "NULL";
			else
				SQL << ",'" << mNewData[*it] << "'";
			i++;
		}
		SQL << ");";

		if(!mDb->Execute(SQL.str()))
		{
			cout << "Unable to complete the execution of the SQL Request" << endl;
			cout << "Query: " << SQL.str() << endl;
		}
		else
			dataId = mDb->GetLastInsertedRowId();
	}

	if(dataId > 0)
	{
		//If the data was saved, update the local maps
		mId = dataId;
		mData = Load();
		mNewData = mData;
	}

	return dataId;
}

void DbTable::Set(string fieldName, string value)
{
	mNewData[fieldName] = value;
}

void DbTable::ShowTable()
{
	cout << "Table Name: " << mTableName << endl;
	cout << "Columns" << endl;
	cout << "|";
	vector<string> colsName = mDb->GetColumnsName(mTableName);
	for(vector<string>::iterator it = colsName.begin(); it < colsName.end(); ++it)
	{
		cout << " " << *it << " |";
	}
	cout << endl;
	vector<vector<string>> vData = mDb->Query("SELECT * FROM " + mTableName + ";");
	for(vector<vector<string>>::iterator it = vData.begin(); it < vData.end(); ++it)
	{
		cout << "|";
		vector<string> vLine = *it;
		for(vector<string>::iterator it = vLine.begin(); it < vLine.end(); ++it)
		{
			string data = *it;
			cout << data << "|";
		}
		cout << endl;
	}
}